<template>
  <div class="inputWrapper">
    <div
      class="editTool"
      contenteditable="true"
      ref="inputRef"
      @input="updateHtml"
      @keydown.enter.prevent="handleEnter"
      @paste="pasteContent"
    ></div>
    <Button @click="handleEnter">发送</Button>
  </div>
</template>
<script lang="ts" setup>
import { ref, onMounted, computed, onUnmounted } from 'vue'
import { Button } from 'ant-design-vue'
import PubSub from 'pubsub-js'
const emit = defineEmits(['send'])
const inputRef = ref(null)
const content = ref('')
const updateHtml = (e: any) => {
  content.value = e.target.innerHTML
}
 // 自定义粘贴功能
const pasteContent = (event: any) => {
  event.preventDefault();
  // 获取粘贴的数据
  const items = (event.clipboardData || window.clipboardData).items;
  for (let i = 0; i < items.length; i++) {
    const item = items[i];

    if (item.type.indexOf('image') !== -1) {
      // 获取图片文件
      const file = item.getAsFile();
      // 创建一个 FileReader 来读取图片
      const reader = new FileReader();
      reader.onload = function(e) {
        const img = new Image()
        img.src = e.target?.result as string
        img.onload = () => {
          const maxWidth = 100
          const ratio = img.width / img.height
          const height = maxWidth / ratio

          img.style.width = `${maxWidth}px`
          img.style.height = `${height}px`
          appendVNode(img)
        }
      };

      // 读取图片文件
      reader.readAsDataURL(file);
    } else if(item.type==='text/plain') {
      item.getAsString((str: string) => {
        if(str!=='') {
          const textVNode =  document.createTextNode(str)
          appendVNode(textVNode)
        }
      })
    }
  }
}

// 插入节点
const appendVNode = (node: Node) => {
  const range = document.getSelection()?.getRangeAt(0)
  // 插入图片到光标位置
  range?.deleteContents() // 删除选中的内容（如果有的话）
  range?.insertNode(node)
  range?.setStartAfter(node)
  range?.setEndAfter(node)
  // 更新选择
  const selection = window.getSelection()
  selection?.removeAllRanges()
  range && selection?.addRange(range)
  moveCursorToEnd(inputRef.value)
}

// 回车发送事件
const handleEnter = () => {
  if(inputRef.value?.innerHTML) {
    // 获取所有的子节点（包括纯文本和图片节点）
    const childNodes = Array.from(inputRef.value?.childNodes)
    // 归约所有子节点（如果当前子节点是非表情包图片就直接发送图片消息，否则就累计发送）
    const htmlText = childNodes.reduce((prev: string, element: Node, index: Number) => {
      if(element.nodeType === 3) { // 文字节点
        return prev+=element.textContent
      } else if(element.nodeType === 1) { // 图片节点
        if(element.className.indexOf('emotion') !== -1) { //表情包节点
          // 拿到表情包的简写
          const tag = Array.from(element.attributes).find((item)=> item.name === 'tag').value
          return prev+= tag
        } else { // 自定义图片（直接上传图片）
          if(prev!=='') { // 如果之前有文字 或者 文字+表情包就把之前的发送了
            emit('send', { type: 0, message: prev, imgs: '', video: '', volice: '' }); 
          } 
          emit('send', { type: 1, message: '', imgs: [element.currentSrc], video: '', volice: '' }); 
          return ''
        }
      }
    }, "");
    if(htmlText) {
      emit('send', { type: 0, message: htmlText, imgs: "", video: '', volice: '' }); 
    }
    inputRef.value.innerHTML = null
    PubSub.publish('scrollBottom', {  })
  }
}
const moveCursorToEnd = (element: HTMLElement) => {
  const range = document.createRange()
  const selection = window.getSelection()
  // 将范围设置为元素的末尾
  range.selectNodeContents(element)
  range.collapse(false) // 折叠到末尾
  // 清除当前选择并添加新范围
  selection?.removeAllRanges()
  selection?.addRange(range)
}
onMounted(() => {
  inputRef.value?.focus()
  // 订阅插入表情包消息
  PubSub.subscribe('selectEmotion', (msg: string, data: any) => {
    if (inputRef.value && data.index !== null) {
      inputRef.value?.focus()
      //将光标移到最后面
      moveCursorToEnd(inputRef.value)
      const img = document.createElement('img')
      img.src = data.data.path // 假设 getEmotionImgLabel 返回的对象包含 imgSrc 属性
      img.style.width = '20px' // 根据需要设置样式
      img.style.height = '20px'
      img.className='emotion'
      img.setAttribute('tag', data.data.alias);
      appendVNode(img)
    }
  })
})
onUnmounted(()=> {
  PubSub.unsubscribe('selectEmotion')
})
</script>
<style lang="less" scoped>
.inputWrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
  .editTool {
    width: 100%;
    margin-top: 10px;
    border: none;
    outline: none;
    resize: none;
    background-color: transparent;
    font-size: 13.5px;
    flex: 1;
    display: flex;
    line-height: 2;
    img {
      max-width: 50px;
    }
  }
  button {
    width: 100px;
    float: right;
    background-color: #ededed;
    color: #07c160;
    border: none;
    align-self: flex-end;
    align-items: flex-end;
  }
}
</style>
